package icu.d4peng.cloud.common.http.properties;

import com.dtflys.forest.backend.HttpBackend;
import com.dtflys.forest.backend.HttpBackendSelector;
import com.dtflys.forest.backend.okhttp3.OkHttp3Backend;
import com.dtflys.forest.callback.*;
import com.dtflys.forest.converter.ForestConverter;
import com.dtflys.forest.converter.json.ForestFastjsonConverter;
import com.dtflys.forest.converter.protobuf.ForestGoogleProtobufConverter;
import com.dtflys.forest.converter.text.DefaultTextConverter;
import com.dtflys.forest.converter.xml.ForestJaxbConverter;
import com.dtflys.forest.interceptor.Interceptor;
import com.dtflys.forest.logging.DefaultLogHandler;
import com.dtflys.forest.logging.ForestLogHandler;
import com.dtflys.forest.retryer.BackOffRetryer;
import com.dtflys.forest.retryer.ForestRetryer;
import com.dtflys.forest.ssl.SSLUtils;
import com.dtflys.forest.utils.ForestDataType;
import icu.d4peng.cloud.common.http.config.RocLogHandler;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author d4peng
 * @version 1.0.0
 * @date 2021-12-30 17:04
 * @description HttpProperties:Http属性
 */
@ConfigurationProperties(prefix = HttpProperties.PREFIX)
public class HttpProperties {
    /**
     * 前缀
     */
    public static final String PREFIX = "roc.http";
    /**
     * 是否开启:默认开启
     */
    private boolean enabled = true;
    /**
     * 连接池最大连接数（默认为 500）
     */
    private int maxConnections = 500;
    /**
     * 每个路由的最大连接数（默认为 500）
     */
    private int maxRouteConnections = 500;
    /**
     * 最大异步线程池大小
     */
    private int maxAsyncThreadSize = 100;
    /**
     * 全局的请求超时时间，单位为毫秒
     */
    private int timeout = 3000;
    /**
     * 全局的请求连接超时时间，单位为毫秒
     */
    private int connectTimeout = 3000;
    /**
     * 全局的请求读取超时时间，单位为毫秒
     */
    private int readTimeout = 3000;
    /**
     * 全局的请求数据字符集
     */
    private String charset = "UTF-8";
    /**
     * 全局HTTP协议:http,https
     */
    private String addressScheme;
    /**
     * 主机地址(主机名/ip地址)
     */
    private String addressHost;
    /**
     * 主机端口号
     */
    private int addressPort = -1;
    /**
     * 全局默认的主机地址信息动态来源接口实现类,这里可以做一次Nacos的实现
     */
    private Class<? extends AddressSource> baseAddressSourceClass;
    /**
     * 全局的请求失败重试策略类
     */
    private Class<? extends ForestRetryer> retryer = BackOffRetryer.class;
    /**
     * 全局的最大请求失败重试次数
     */
    private int maxRetryCount = 0;
    /**
     * 全局的最大请求重试之间的时间间隔，单位为毫秒
     */
    private long maxRetryInterval = 0;
    /**
     * 是否自动重定向开关
     */
    private boolean autoRedirection = true;
    /**
     * 是否允许打印请求/响应日志
     */
    private boolean logEnabled = true;
    /**
     * 是否允许打印请求/响应日志
     */
    private boolean logRequest = true;
    /**
     * 是否允许打印响应状态日志
     */
    private boolean logResponseStatus = true;
    /**
     * 是否允许打印响应内容日志
     */
    private boolean logResponseContent = false;
    /**
     * 日志处理器
     */
    private Class<? extends ForestLogHandler> logHandler = DefaultLogHandler.class;
    /**
     * 全局的单向HTTPS请求的SSL协议，默认为 TLSv1.2
     */
    private String sslProtocol = SSLUtils.TLS_1_2;
    /**
     * HTTP后端:httpclient,okhttp3
     */
    private String backend = "httpclient";
    /**
     * 全局变量表
     */
    private Map<String, Object> variables = new ConcurrentHashMap<>(64);
    /**
     * 全局拦截器列表
     */
    @SuppressWarnings("rawtypes")
    private List<Class<? extends Interceptor>> interceptors = new ArrayList<>();
    /**
     * 全局请求成功条件回调函数类
     */
    private Class<? extends SuccessWhen> successWhenClass = DefaultSuccessWhen.class;
    /**
     * 全局重试条件回调函数
     */
    private Class<? extends RetryWhen> retryWhenClass = DefaultRetryWhen.class;
    /**
     * SSL的Key Store集合
     */
    private List<HttpSSLKeyStoreProperties> sslKeyStores = new ArrayList<>();
    /**
     * 转换属性集合
     */
    @SuppressWarnings("rawtypes")
    private Map<ForestDataType, ForestConverter> converters = new HashMap<>();
    /**
     * 过滤器
     */
    private Map<String, Class<?>> filters = new HashMap<>();

    private HttpBackendSelector httpBackendSelector = new HttpBackendSelector();

    public HttpBackendSelector getHttpBackendSelector() {
        return httpBackendSelector;
    }

    public HttpProperties setHttpBackendSelector(HttpBackendSelector httpBackendSelector) {
        this.httpBackendSelector = httpBackendSelector;
        return this;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public HttpProperties setEnabled(boolean enabled) {
        this.enabled = enabled;
        return this;
    }

    public int getMaxConnections() {
        return maxConnections;
    }

    public HttpProperties setMaxConnections(int maxConnections) {
        this.maxConnections = maxConnections;
        return this;
    }

    public int getMaxRouteConnections() {
        return maxRouteConnections;
    }

    public HttpProperties setMaxRouteConnections(int maxRouteConnections) {
        this.maxRouteConnections = maxRouteConnections;
        return this;
    }

    public int getMaxAsyncThreadSize() {
        return maxAsyncThreadSize;
    }

    public HttpProperties setMaxAsyncThreadSize(int maxAsyncThreadSize) {
        this.maxAsyncThreadSize = maxAsyncThreadSize;
        return this;
    }

    public int getTimeout() {
        return timeout;
    }

    public HttpProperties setTimeout(int timeout) {
        this.timeout = timeout;
        return this;
    }

    public int getConnectTimeout() {
        return connectTimeout;
    }

    public HttpProperties setConnectTimeout(int connectTimeout) {
        this.connectTimeout = connectTimeout;
        return this;
    }

    public int getReadTimeout() {
        return readTimeout;
    }

    public HttpProperties setReadTimeout(int readTimeout) {
        this.readTimeout = readTimeout;
        return this;
    }

    public String getCharset() {
        return charset;
    }

    public HttpProperties setCharset(String charset) {
        this.charset = charset;
        return this;
    }

    public String getAddressScheme() {
        return addressScheme;
    }

    public HttpProperties setAddressScheme(String addressScheme) {
        this.addressScheme = addressScheme;
        return this;
    }

    public String getAddressHost() {
        return addressHost;
    }

    public HttpProperties setAddressHost(String addressHost) {
        this.addressHost = addressHost;
        return this;
    }

    public int getAddressPort() {
        return addressPort;
    }

    public HttpProperties setAddressPort(int addressPort) {
        this.addressPort = addressPort;
        return this;
    }

    public Class<? extends AddressSource> getBaseAddressSourceClass() {
        return baseAddressSourceClass;
    }

    public HttpProperties setBaseAddressSourceClass(Class<? extends AddressSource> baseAddressSourceClass) {
        this.baseAddressSourceClass = baseAddressSourceClass;
        return this;
    }

    public Class<? extends ForestRetryer> getRetryer() {
        return retryer;
    }

    public HttpProperties setRetryer(Class<? extends ForestRetryer> retryer) {
        this.retryer = retryer;
        return this;
    }

    public int getMaxRetryCount() {
        return maxRetryCount;
    }

    public HttpProperties setMaxRetryCount(int maxRetryCount) {
        this.maxRetryCount = maxRetryCount;
        return this;
    }

    public long getMaxRetryInterval() {
        return maxRetryInterval;
    }

    public HttpProperties setMaxRetryInterval(long maxRetryInterval) {
        this.maxRetryInterval = maxRetryInterval;
        return this;
    }

    public boolean isAutoRedirection() {
        return autoRedirection;
    }

    public HttpProperties setAutoRedirection(boolean autoRedirection) {
        this.autoRedirection = autoRedirection;
        return this;
    }

    public boolean isLogEnabled() {
        return logEnabled;
    }

    public HttpProperties setLogEnabled(boolean logEnabled) {
        this.logEnabled = logEnabled;
        return this;
    }

    public boolean isLogRequest() {
        return logRequest;
    }

    public HttpProperties setLogRequest(boolean logRequest) {
        this.logRequest = logRequest;
        return this;
    }

    public boolean isLogResponseStatus() {
        return logResponseStatus;
    }

    public HttpProperties setLogResponseStatus(boolean logResponseStatus) {
        this.logResponseStatus = logResponseStatus;
        return this;
    }

    public boolean isLogResponseContent() {
        return logResponseContent;
    }

    public HttpProperties setLogResponseContent(boolean logResponseContent) {
        this.logResponseContent = logResponseContent;
        return this;
    }

    public Class<? extends ForestLogHandler> getLogHandler() {
        return logHandler;
    }

    public HttpProperties setLogHandler(Class<? extends ForestLogHandler> logHandler) {
        this.logHandler = logHandler;
        return this;
    }

    public String getSslProtocol() {
        return sslProtocol;
    }

    public HttpProperties setSslProtocol(String sslProtocol) {
        this.sslProtocol = sslProtocol;
        return this;
    }

    public String getBackend() {
        return backend;
    }

    public HttpProperties setBackend(String backend) {
        this.backend = backend;
        return this;
    }

    public Map<String, Object> getVariables() {
        return variables;
    }

    public HttpProperties setVariables(Map<String, Object> variables) {
        this.variables = variables;
        return this;
    }

    public List<Class<? extends Interceptor>> getInterceptors() {
        return interceptors;
    }

    public HttpProperties setInterceptors(List<Class<? extends Interceptor>> interceptors) {
        this.interceptors = interceptors;
        return this;
    }

    public Class<? extends SuccessWhen> getSuccessWhenClass() {
        return successWhenClass;
    }

    public HttpProperties setSuccessWhenClass(Class<? extends SuccessWhen> successWhenClass) {
        this.successWhenClass = successWhenClass;
        return this;
    }

    public Class<? extends RetryWhen> getRetryWhenClass() {
        return retryWhenClass;
    }

    public HttpProperties setRetryWhenClass(Class<? extends RetryWhen> retryWhenClass) {
        this.retryWhenClass = retryWhenClass;
        return this;
    }

    public List<HttpSSLKeyStoreProperties> getSslKeyStores() {
        return sslKeyStores;
    }

    public HttpProperties setSslKeyStores(List<HttpSSLKeyStoreProperties> sslKeyStores) {
        this.sslKeyStores = sslKeyStores;
        return this;
    }

    public HttpProperties setConverters(Map<ForestDataType, ForestConverter> converters) {
        this.converters = converters;
        return this;
    }

    public Map<String, Class<?>> getFilters() {
        return filters;
    }

    public HttpProperties setFilters(Map<String, Class<?>> filters) {
        this.filters = filters;
        return this;
    }

    @SuppressWarnings("rawtypes")
    public Map<ForestDataType, ForestConverter> getConverters() {
        this.converters.put(ForestDataType.TEXT, new DefaultTextConverter());
        this.converters.put(ForestDataType.JSON, new ForestFastjsonConverter());
        this.converters.put(ForestDataType.XML, new ForestJaxbConverter());
        this.converters.put(ForestDataType.PROTOBUF, new ForestGoogleProtobufConverter());

        return converters;
    }
}
